package com.loong.android.webview;

import static android.app.Activity.RESULT_CANCELED;
import static android.app.Activity.RESULT_OK;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Build;
import android.os.Message;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.ViewParent;
import android.webkit.ConsoleMessage;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.GeolocationPermissions;
import android.webkit.JsPromptResult;
import android.webkit.JsResult;
import android.webkit.PermissionRequest;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebViewClient;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.loong.android.LonWin;
import com.loong.android.WinLife;
import com.loong.android.views.LonView;
import com.loong.android.views.utils.ViewImpl;
import com.loong.android.views.utils.ViewTemplate;

import java.util.HashMap;
import java.util.Map;

public class LonWebView extends android.webkit.WebView implements ViewTemplate {

    private final ViewImpl viewImpl = new ViewImpl(this);

    public LonWebView(Context context) {
        super(context);
        initAttrs(context, null);
    }

    public LonWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initAttrs(context, attrs);
    }

    public LonWebView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initAttrs(context, attrs);
    }

    private void initAttrs(Context context, AttributeSet attrs) {
        if (context == null) return;
        viewImpl.initView(context, attrs);
        viewImpl.drawBackgroundDrawable();
        initSetting();
        initEvent();
    }

    private void initSetting() {
        WebSettings settings = getSettings();
        // 特别注意：5.1以上默认禁止了https和http混用，以下方式是开启
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
        }
        //启用js
        settings.setJavaScriptEnabled(true);
        settings.setDomStorageEnabled(true);
        //启用数据库缓存
        settings.setDatabaseEnabled(true);
        //启用宽视口
        settings.setUseWideViewPort(true);
        //启用概览模式
        settings.setLoadWithOverviewMode(true);
        //允许js弹窗
        settings.setJavaScriptCanOpenWindowsAutomatically(true);
        //启用地理定位
        settings.setGeolocationEnabled(true);
        //允许访问文件
        settings.setAllowFileAccess(true);
    }

    //region 自定义的方法

    /**
     * 打开网址并提交数据
     * @param url 网址
     * @param postData 提交的数据，格式为键值对：key=value&key=value&……
     */
    public void loadUrl(String url, String postData) {
        postUrl(url, postData.getBytes());
    }

    /**
     * 打开某个网址并附带头部信息(header)
     * @param url 网址
     * @param headers 头部信息键值对数组，格式如：[[键名, 键值], [键名, 键值], ...]
     */
    public void loadUrl(String url, String[][] headers) {
        Map<String, String> map = new HashMap<>();
        if(headers != null) {
            for (String[] header : headers) {
                map.put(header[0], header[1]);
            }
        }
        loadUrl(url, map);
    }

    /**
     * 设置cookie
     * @param url 网址，如：www.baidu.com
     * @param content cookie内容
     */
    public void setCookie(String url, String content) {
        CookieManager cookieManager = CookieManager.getInstance();
        cookieManager.setAcceptCookie(true);
        cookieManager.setCookie(url, content);
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            CookieSyncManager.createInstance(getContext());
            CookieSyncManager.getInstance().sync();
        } else {
            cookieManager.flush();
        }
    }

    public String getCookie(String url) {
        return CookieManager.getInstance().getCookie(url);
    }

    /**
     * 清除浏览器的cookie
     */
    public void clearCookie() {
        CookieManager cookieManager = CookieManager.getInstance();
        cookieManager.setAcceptCookie(true);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            cookieManager.removeAllCookies(null);
            cookieManager.removeSessionCookies(null);
            cookieManager.flush();
        } else {
            CookieSyncManager.createInstance(getContext());
            CookieSyncManager.getInstance().sync();
        }
    }

    /**
     * 网页快照
     */
    public Bitmap snapshot() {
        Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        draw(canvas);
        return bitmap;
    }

    /**
     * 添加JavaScript接口，注意：android api < 17无效
     * @param name 接口名称
     * @param event 回调事件
     */
    public void addJavascriptInterface(String name, JavascriptInterface event) {
        super.addJavascriptInterface(new Object() {

            @android.webkit.JavascriptInterface
            public void send(String str) {
                if (event != null) event.send(str);
            }

            @android.webkit.JavascriptInterface
            public void sendWithTag(String str1, String str2) {
                if (event != null) event.sendWithTag(str1, str2);
            }

            @android.webkit.JavascriptInterface
            public void sendArray(String[] arr) {
                if (event != null) event.sendArray(arr);
            }

            @android.webkit.JavascriptInterface
            public void sendArrayWithTag(String tag, String[] arr) {
                if (event != null) event.sendArrayWithTag(tag, arr);
            }

        }, name);
    }

    /**
     * 删除JavaScript接口
     * @param name 接口名称
     */
    public void removeJavascriptInterface(String name) {
        super.removeJavascriptInterface(name);
    }

    /************************滚动条相关**************************/

    /**
     * 设置滚动条模式
     *
     * @param style 风格，参考常量：ScrollBarStyle.***
     */
    public void scrollBarStyle(int style) {
        setScrollBarStyle(style);
    }

    /**
     * 取滚动条模式
     */
    public int scrollBarStyle() {
        return getScrollBarStyle();
    }

    /**
     * 置滚动条大小
     *
     * @param size 滚动条大小
     */
    public void scrollBarSize(int size) {
        setScrollBarSize(size);
    }

    /**
     * 取滚动条大小
     */
    public int scrollBarSize() {
        return getScrollBarSize();
    }

    /**
     * 滚动到指定位置
     *
     * @param x 横向位置
     * @param y 纵向位置
     */
    public void scrollTo(int x, int y) {
        super.scrollTo(x, y);
    }

    /**
     * 滚动指定的距离
     *
     * @param dx 横向距离
     * @param dy 纵向距离
     */
    public void scrollBy(int dx, int dy) {
        super.scrollBy(dx, dy);
    }

    /**
     * 取横向滚动条位置
     */
    public int getScrollPositionX() {
        return getScrollX();
    }

    /**
     * 取纵向滚动条位置
     */
    public int getScrollPositionY() {
        return getScrollY();
    }

    /**
     * 设置是否显示横向滚动条
     * @param enable 是否显示
     */
    public void scrollBarXEnable(boolean enable) {
        setHorizontalScrollBarEnabled(enable);
    }

    /**
     * 设置是否显示纵向滚动条
     * @param enable 是否显示
     */
    public void scrollBarYEnable(boolean enable) {
        setVerticalScrollBarEnabled(enable);
    }

    /**
     * 获取横向滚动条的启用状态
     */
    public boolean scrollBarXEnable() {
        return isHorizontalScrollBarEnabled();
    }

    /**
     * 获取纵向滚动条的启用状态
     */
    public boolean scrollBarYEnable() {
        return isVerticalScrollBarEnabled();
    }

    /**
     * 设置滚动条可否渐隐
     * @param enable 是否开启
     */
    public void scrollBarFadingEnable(boolean enable) {
        setScrollbarFadingEnabled(enable);
    }

    /**
     * 取滚动条可否渐隐
     */
    public boolean scrollBarFadingEnable() {
        return isScrollbarFadingEnabled();
    }

    /**
     * 设置滚动条延迟渐隐的时间
     * @param delayTime 延迟时间，单位为毫秒
     */
    public void scrollBarDelayFadeTime(int delayTime) {
        setScrollBarDefaultDelayBeforeFade(delayTime);
    }

    /**
     * 取滚动条延迟渐隐的时间
     */
    public int scrollBarDelayFadeTime() {
        return getScrollBarDefaultDelayBeforeFade();
    }

    /**
     * 设置滚动条渐隐的持续时间
     * @param duration 持续时间，单位为毫秒
     */
    public void scrollBarFadeDuration(int duration) {
        setScrollBarFadeDuration(duration);
    }

    /**
     * 取滚动条渐隐的持续时间
     */
    public int scrollBarFadeDuration() {
        return getScrollBarFadeDuration();
    }

    /******************View基础******************/

    /**
     * 取宽度
     */
    @Override
    public int width() {
        return viewImpl.width();
    }

    /**
     * 置宽度
     *
     * @param w 宽度
     */
    @Override
    public void width(int w) {
        viewImpl.width(w);
    }

    /**
     * 取高度
     */
    @Override
    public int height() {
        return viewImpl.height();
    }

    /**
     * 置高度
     *
     * @param h 高度
     */
    @Override
    public void height(int h) {
        viewImpl.height(h);
    }

    /**
     * 设置宽度和高度
     *
     * @param w 宽度
     * @param h 高度
     */
    @Override
    public void setWidthHeight(int w, int h) {
        viewImpl.setWidthHeight(w, h);
    }

    /**
     * 设置最小宽度
     *
     * @param w 宽度
     */
    @Override
    public void minWidth(int w) {
        viewImpl.minWidth(w);
    }

    /**
     * 取最小宽度
     */
    @Override
    public int minWidth() {
        return viewImpl.minWidth();
    }

    /**
     * 设置最小高度
     *
     * @param h 高度
     */
    @Override
    public void minHeight(int h) {
        viewImpl.minHeight(h);
    }

    /**
     * 取最小高度
     */
    @Override
    public int minHeight() {
        return viewImpl.minHeight();
    }

    /**
     * 设置描述内容(setContentDescription)
     *
     * @param des 描述
     */
    @Override
    public void description(String des) {
        viewImpl.description(des);
    }

    /**
     * 取描述内容(ContentDescription)
     */
    @Override
    public String description() {
        return viewImpl.description();
    }

    /**
     * 置标签数据
     *
     * @param t 数据
     */
    @Override
    public void tag(Object t) {
        viewImpl.tag(t);
    }

    /**
     * 置标签数据
     *
     * @param key 键名
     * @param t   数据
     */
    @Override
    public void tag(int key, Object t) {
        viewImpl.tag(key, t);
    }

    /**
     * 取标签数据
     */
    @Override
    public Object tag() {
        return viewImpl.tag();
    }

    /**
     * 取标签数据
     *
     * @param key 键名
     */
    @Override
    public Object tag(int key) {
        return viewImpl.tag(key);
    }

    /**
     * 设置透明度
     *
     * @param a 透明度，0-1
     */
    @Override
    public void alpha(float a) {
        viewImpl.alpha(a);
    }

    /**
     * 取透明度
     *
     * @return 0-1
     */
    @Override
    public float alpha() {
        return viewImpl.alpha();
    }

    /**
     * 置内边距
     *
     * @param left   左内边距
     * @param top    上内边距
     * @param right  右内边距
     * @param bottom 下内边距
     */
    @Override
    public void padding(int left, int top, int right, int bottom) {
        viewImpl.padding(left, top, right, bottom);
    }

    /**
     * 置水平方向的内边距
     *
     * @param left  左内边距
     * @param right 上内边距
     */
    @Override
    public void paddingX(int left, int right) {
        viewImpl.paddingX(left, right);
    }

    /**
     * 置垂直方向的内边距
     *
     * @param top    上内边距
     * @param bottom 下内边距
     */
    @Override
    public void paddingY(int top, int bottom) {
        viewImpl.paddingY(top, bottom);
    }

    /**
     * 置左内边距
     *
     * @param val 值
     */
    @Override
    public void paddingLeft(int val) {
        viewImpl.paddingLeft(val);
    }

    /**
     * 取左内边距
     */
    @Override
    public int paddingLeft() {
        return viewImpl.paddingLeft();
    }

    /**
     * 置上内边距
     *
     * @param val 值
     */
    @Override
    public void paddingTop(int val) {
        viewImpl.paddingTop(val);
    }

    /**
     * 取上内边距
     */
    @Override
    public int paddingTop() {
        return viewImpl.paddingTop();
    }

    /**
     * 置右内边距
     *
     * @param val 值
     */
    @Override
    public void paddingRight(int val) {
        viewImpl.paddingRight(val);
    }

    /**
     * 取右内边距
     */
    @Override
    public int paddingRight() {
        return viewImpl.paddingRight();
    }

    /**
     * 置下内边距
     *
     * @param val 值
     */
    @Override
    public void paddingBottom(int val) {
        viewImpl.paddingBottom(val);
    }

    /**
     * 取下内边距
     */
    @Override
    public int paddingBottom() {
        return viewImpl.paddingBottom();
    }

    /**
     * 置外边距
     *
     * @param left   左外边距
     * @param top    上外边距
     * @param right  右外边距
     * @param bottom 下外边距
     */
    @Override
    public void margin(int left, int top, int right, int bottom) {
        viewImpl.margin(left, top, right, bottom);
    }

    /**
     * 置水平方向的外边距
     *
     * @param left  左外边距
     * @param right 右外边距
     */
    @Override
    public void marginX(int left, int right) {
        viewImpl.marginX(left, right);
    }

    /**
     * 置垂直方向的外边距
     *
     * @param top    上外边距
     * @param bottom 下外边距
     */
    @Override
    public void marginY(int top, int bottom) {
        viewImpl.marginY(top, bottom);
    }

    /**
     * 置左外边距
     *
     * @param val 值
     */
    @Override
    public void marginLeft(int val) {
        viewImpl.marginLeft(val);
    }

    /**
     * 取左外边距
     */
    @Override
    public int marginLeft() {
        return viewImpl.marginLeft();
    }

    /**
     * 置上外边距
     *
     * @param val 值
     */
    @Override
    public void marginTop(int val) {
        viewImpl.marginTop(val);
    }

    /**
     * 取上外边距
     */
    @Override
    public int marginTop() {
        return viewImpl.marginTop();
    }

    /**
     * 置右外边距
     *
     * @param val 值
     */
    @Override
    public void marginRight(int val) {
        viewImpl.marginRight(val);
    }

    /**
     * 取右外边距
     */
    @Override
    public int marginRight() {
        return viewImpl.marginRight();
    }

    /**
     * 置下外边距
     *
     * @param val 值
     */
    @Override
    public void marginBottom(int val) {
        viewImpl.marginBottom(val);
    }

    /**
     * 取下外边距
     */
    @Override
    public int marginBottom() {
        return viewImpl.marginBottom();
    }

    /**
     * 置可视状态
     *
     * @param v 可视状态，GONE: 消失不占位；INVISIBLE: 隐藏; VISIBLE: 可视
     */
    @Override
    public void visibility(int v) {
        viewImpl.visibility(v);
    }

    /**
     * 取可视状态
     *
     * @return GONE: 消失不占位；INVISIBLE: 隐藏; VISIBLE: 可视
     */
    @Override
    public int visibility() {
        return viewImpl.visibility();
    }


    /**
     * 关闭硬件加速
     */
    @Override
    public void closeHardwareAcceleration() {
        viewImpl.closeHardwareAcceleration();
    }

    /**
     * 从父布局中删除自己
     */
    @Override
    public void removeSelf() {
        viewImpl.removeSelf();
    }

    /**
     * 显示到顶层
     */
    @Override
    public void toTop() {
        viewImpl.toTop();
    }

    /**
     * 取上下文
     */
    @Override
    public Context getViewContext() {
        return viewImpl.getViewContext();
    }

    /**
     * 取id
     */
    @Override
    public int getViewId() {
        return viewImpl.getViewId();
    }

    /**
     * 置视图id，需要android api 17才能使用
     */
    @Override
    public int setViewId() {
        return viewImpl.setViewId();
    }

    /**
     * 取类的名称
     */
    @Override
    public String getClassSimpleName() {
        return viewImpl.getClassSimpleName();
    }

    /**
     * 取父布局对象
     */
    @Override
    public ViewParent getViewParent() {
        return viewImpl.getParentView();
    }

    /**
     * 取父布局id
     */
    @Override
    public int getViewParentId() {
        return viewImpl.getParentId();
    }

    /**
     * 置启用状态
     *
     * @param enabled 是否启用
     */
    @Override
    public void setEnabled(boolean enabled) {
        viewImpl.setEnabled(enabled);
    }

    /**
     * 获取焦点
     */
    @Override
    public void focus() {
        viewImpl.focus();
    }

    /**
     * 取消焦点
     */
    @Override
    public void blur() {
        viewImpl.blur();
    }

    /**
     * 置可否单击，默认为 false，若为 false，将无法产生click事件，onTouch事件中也无法触发弹起事件: ACTION_UP
     * 调用 setOnClick 函数后，自动置为 true
     *
     * @param enable 可否
     */
    @Override
    public void clickable(boolean enable) {
        viewImpl.clickable(enable);
    }

    /**
     * 置可否触发长按事件，默认为 false，若为false，无法触发longClick事件
     * 调用 setOnLongClick 函数后，自动置为 true
     *
     * @param enable 可否
     */
    @Override
    public void longClickable(boolean enable) {
        viewImpl.longClickable(enable);
    }

    /**
     * 置可获取焦点，使得组件在非触屏设备上拥有获取焦点的能力。
     *
     * @param enable 是否获取
     */
    @Override
    public void focusable(boolean enable) {
        viewImpl.focusable(enable);
    }

    /**
     * 置可获取触摸屏模式的焦点，使得组件在触屏模式下获取焦点的能力
     *
     * @param enable 是否获取
     */
    @Override
    public void focusableInTouchMode(boolean enable) {
        viewImpl.focusableInTouchMode(enable);
    }

    /**
     * 设置背景颜色
     *
     * @param color 颜色
     */
    @Override
    public void backgroundColor(int color) {
        viewImpl.backgroundColor(color);
    }

    /**
     * 取背景颜色
     */
    @Override
    public int backgroundColor() {
        return viewImpl.backgroundColor();
    }


    /**
     * 设置线性渐变背景
     * @param x0 起点横坐标。0-1表示按视图宽度比例计算，大于1和小于等于0表示固定的像素值。默认值为0，表示在视图水平靠左的位置。
     * @param y0 起点纵坐标。0-1表示按视图高度比例计算，大于1和小于等于0表示固定的像素值。默认值为0，表示在视图垂直靠上的位置。
     * @param x1 终点横坐标。0-1表示按视图宽度比例计算，大于1和小于等于0表示固定的像素值。默认值为1，表示在视图水平靠右的位置。
     * @param y1 终点纵坐标。0-1表示按视图高度比例计算，大于1和小于等于0表示固定的像素值。默认值为1，表示在视图垂直靠下的位置。
     * @param colors 颜色数组，不同位置的颜色值
     * @param positions 位置数组，指定各个颜色的位置。设置的值范围时0-1，0表示起始位置, 1表示结束位置
     * @param mode 平铺方式，参考"TileMode"类的常量
     */
    @Override
    public void setBackgroundLinearGradient(float x0, float y0, float x1, float y1, int[] colors, float[] positions, int mode) {
        viewImpl.setBackgroundLinearGradient(x0, y0, x1, y1, colors, positions, mode);
    }

    /**
     * 设置线性渐变背景
     * @param x0 起点横坐标。0-1表示按视图宽度比例计算，大于1和小于等于0表示固定的像素值。默认值为0，表示在视图水平靠左的位置。
     * @param y0 起点纵坐标。0-1表示按视图高度比例计算，大于1和小于等于0表示固定的像素值。默认值为0，表示在视图垂直靠上的位置。
     * @param x1 终点横坐标。0-1表示按视图宽度比例计算，大于1和小于等于0表示固定的像素值。默认值为1，表示在视图水平靠右的位置。
     * @param y1 终点纵坐标。0-1表示按视图高度比例计算，大于1和小于等于0表示固定的像素值。默认值为1，表示在视图垂直靠下的位置。
     * @param color1 开始的颜色值
     * @param color2 结束的颜色值
     * @param mode 平铺方式，参考"TileMode"类的常量
     */
    @Override
    public void setBackgroundLinearGradient(float x0, float y0, float x1, float y1, int color1, int color2, int mode) {
        viewImpl.setBackgroundLinearGradient(x0, y0, x1, y1, color1, color2, mode);
    }

    /**
     * 设置环形渐变背景
     * @param centerX 中心点横坐标，0-1表示百分比，大于1和小于等于0表示固定的像素值。默认值为0.5f，表示在视图水平方向的中间位置。
     * @param centerY 中心点纵坐标，0-1表示百分比，大于1和小于等于0表示固定的像素值。默认值为0.5f，表示在视图垂直方向的中间位置。
     * @param radius 环形的半径，小于0时表示按视图宽度或高度的比例计算。
     *               大于等于0表示固定的像素值；
     *               -1 <= radius < 0 时，表示按短边的比例计算；
     *               -2 <= radius < -1 时，表示按长边的比例计算。
     *               -3 <= radius < -2 时，表示按视图宽度的比例计算。
     *               -4 <= radius < -3 时，表示按视图高度的比例计算。
     *               默认值为-1，即半径为视图最短边的长度。
     * @param colors 颜色数组，不同位置的颜色值
     * @param stops 位置数组，指定各个颜色的位置。设置的值范围时0-1，0表示起始位置, 1表示结束位置
     * @param mode 平铺方式，参考"TileMode"类的常量
     */
    @Override
    public void setBackgroundRadialGradient(float centerX, float centerY, float radius, int[] colors, float[] stops, int mode) {
        viewImpl.setBackgroundRadialGradient(centerX, centerY, radius, colors, stops, mode);
    }

    /**
     * 设置环形渐变背景
     * @param centerX 中心点横坐标，0-1表示百分比，大于1和小于等于0表示固定的像素值。默认值为0.5f，表示在视图水平方向的中间位置。
     * @param centerY 中心点纵坐标，0-1表示百分比，大于1和小于等于0表示固定的像素值。默认值为0.5f，表示在视图垂直方向的中间位置。
     * @param radius 环形的半径，小于0时表示按视图宽度或高度的比例计算。
     *               大于等于0表示固定的像素值；
     *               -1 <= radius < 0 时，表示按短边的比例计算；
     *               -2 <= radius < -1 时，表示按长边的比例计算。
     *               -3 <= radius < -2 时，表示按视图宽度的比例计算。
     *               -4 <= radius < -3 时，表示按视图高度的比例计算。
     *               默认值为-1，即半径为视图最短边的长度。
     * @param centerColor 中心点颜色
     * @param edgeColor 边缘颜色
     * @param mode 平铺方式，参考"TileMode"类的常量
     */
    @Override
    public void setBackgroundRadialGradient(float centerX, float centerY, float radius, int centerColor, int edgeColor, int mode) {
        viewImpl.setBackgroundRadialGradient(centerX, centerY, radius, centerColor, edgeColor, mode);
    }

    /**
     * 同时设置视图的四个角的圆角大小
     *
     * @param radius 圆角大小
     */
    @Override
    public void corner(int radius) {
        viewImpl.corner(radius);
    }

    /**
     * 分别设置视图四个角的圆角大小
     *
     * @param topLeft     左上角
     * @param topRight    右上角
     * @param bottomRight 右下角
     * @param bottomLeft  左下角
     */
    @Override
    public void corner(float topLeft, float topRight, float bottomRight, float bottomLeft) {
        viewImpl.corner(topLeft, topRight, bottomRight, bottomLeft);
    }

    /**
     * 视图有四个角，每个角有x和y两个方向的圆角大小，共8个圆角值
     *
     * @param topLeftX     左上角x方向的圆角大小
     * @param topLeftY     左上角y方向的圆角大小
     * @param topRightX    右上角x方向的圆角大小
     * @param topRightY    右上角y方向的圆角大小
     * @param bottomRightX 右下角x方向的圆角大小
     * @param bottomRightY 右下角y方向的圆角大小
     * @param bottomLeftX  左下角x方向的圆角大小
     * @param bottomLeftY  左下角y方向的圆角大小
     */
    @Override
    public void corner(float topLeftX, float topLeftY, float topRightX, float topRightY,
                       float bottomRightX, float bottomRightY, float bottomLeftX, float bottomLeftY) {
        viewImpl.corner(topLeftX, topLeftY, topRightX, topRightY, bottomRightX, bottomRightY, bottomLeftX, bottomLeftY);
    }

    /**
     * 设置视图圆角化，其内部的子视图不会遮盖圆角
     * @param radius 圆角大小，单位为px
     */
    public void cornerClip(float radius) {
        viewImpl.setCornerClip(radius);
    }

    /**
     * 取消视图的圆角化
     */
    public void cancelCornerClip() {
        viewImpl.cancelCornerClip();
    }

    /**
     * 置边框宽度
     *
     * @param w 宽度
     */
    @Override
    public void borderWidth(int w) {
        viewImpl.borderWidth(w);
    }

    /**
     * 取边框宽度
     */
    @Override
    public int borderWidth() {
        return viewImpl.borderWidth();
    }

    /**
     * 置边框颜色
     *
     * @param color 颜色
     */
    @Override
    public void borderColor(int color) {
        viewImpl.borderColor(color);
    }

    /**
     * 取边框颜色
     */
    @Override
    public int borderColor() {
        return viewImpl.borderColor();
    }

    /**
     * 取背景图片的位图数据
     */
    @Override
    public Bitmap getBackgroundBitmap() {
        return viewImpl.getBackgroundBitmap();
    }

    /**
     * 置背景图片
     *
     * @param resId 图片资源id
     */
    @Override
    public void background(int resId) {
        viewImpl.background(resId);
    }

    /**
     * 置背景图片
     *
     * @param bitmap 图片位图数据
     */
    @Override
    public void background(Bitmap bitmap) {
        viewImpl.background(bitmap);
    }

    /**
     * 置背景图片，注意需要先申请读取文件的权限(READ_EXTERNAL_STORAGE)
     *
     * @param filePath 图片文件地址
     */
    @Override
    public void background(String filePath) {
        viewImpl.background(filePath);
    }

    /**
     * 置背景图片
     *
     * @param bytes 字节数组
     */
    @Override
    public void background(byte[] bytes) {
        viewImpl.background(bytes);
    }

    /**
     * 置水波纹特效，注意设置该特效后，组件的其他圆角、阴影，边框等效果均失效。
     * @param enable 是否启用
     */
    @Override
    public void setRippleEffectEnable(boolean enable) {
        viewImpl.setRippleEffectEnable(enable);
    }

    /**
     * 置视图可视状态改变的事件回调
     *
     * @param event 回调的接口事件
     */
    @Override
    public void setOnVisibilityChange(LonView.VisibilityChangeCallback event) {
        viewImpl.setOnVisibilityChange(event);
    }

    /**
     * 置视图焦点改变的事件回调
     *
     * @param event 回调的接口事件
     */
    @Override
    public void setOnFocusChange(LonView.FocusChangeCallback event) {
        viewImpl.setOnFocusChange(event);
    }

    /**
     * 置视图尺寸被改变的事件回调
     *
     * @param event 回调的接口事件
     */
    @Override
    public void setOnSizeChange(LonView.SizeChangeCallback event) {
        viewImpl.setOnSizeChange(event);
    }

    /**
     * 置视图生命周期改变的事件回调
     *
     * @param event 回调的接口事件
     */
    @Override
    public void setOnLiftChange(LonView.LifeCallback event) {
        viewImpl.setOnLiftChange(event);
    }

    /**
     * 置被单击的回调事件
     *
     * @param event 回调的接口事件
     */
    @Override
    public void setOnClick(LonView.ClickCallback event) {
        viewImpl.setOnClick(event);
    }

    /**
     * 置被长按的回调
     *
     * @param event 回调的接口事件
     */
    @Override
    public void setOnLongClick(LonView.ClickCallback event) {
        viewImpl.setOnLongClick(event);
    }

    /**
     * 置触摸回调
     *
     * @param touchCallback 回调事件
     */
    @Override
    public void setOnTouch(LonView.TouchCallback touchCallback) {
        viewImpl.setOnTouch(touchCallback);
    }

    @Override
    public void onViewVisibilityChanged(android.view.View view, int visibility) {

    }

    @Override
    public void onViewCreate() {

    }

    @Override
    public void onViewDestroy() {

    }

    @Override
    public void onViewFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {

    }

    @Override
    public void onViewSizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {

    }

    /**
     * 设置客户端事件
     * @param event 事件回调
     */
    public void setClientEvent(ClientEvent event) {
        mClientEvent = event;
    }

    /**
     * 设置客户端事件
     * @param event 事件回调
     */
    public void setChromeClientEvent(ChromeClientEvent event) {
        mChromeClientEvent = event;
    }

    private void initEvent() {
        setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(android.webkit.WebView webView, String url) {
                if (mClientEvent != null) {
                    LonWebView wv = null;
                    if (webView instanceof LonWebView) wv = (LonWebView) webView;
                    Object res = mClientEvent.shouldOverrideUrlLoading(wv, url);
                    if (res instanceof Boolean) return (boolean) res;
                }
                if (url.startsWith("http")) {
                    webView.loadUrl(url);
                } else {
                    try {
                        Context context = webView.getContext();
                        Intent intent = new Intent();
                        intent.setAction(Intent.ACTION_VIEW);
                        intent.setData(Uri.parse(url));
                        context.startActivity(intent);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                return true;
            }

            @Override
            public void onPageStarted(android.webkit.WebView webView, String url, Bitmap favicon) {
                super.onPageStarted(webView, url, favicon);
                if(mClientEvent == null) return;
                LonWebView wv = null;
                if(webView instanceof LonWebView) wv = (LonWebView) webView;
                mClientEvent.onPageStarted(wv, url, favicon);
            }

            @Override
            public void onLoadResource(android.webkit.WebView webView, String url) {
                super.onLoadResource(webView, url);
                if(mClientEvent == null) return;
                LonWebView wv = null;
                if(webView instanceof LonWebView) wv = (LonWebView) webView;
                mClientEvent.onLoadResource(wv, url);
            }

            @Override
            public void onPageFinished(android.webkit.WebView webView, String url) {
                super.onPageFinished(webView, url);
                if(mClientEvent == null) return;
                LonWebView wv = null;
                if(webView instanceof LonWebView) wv = (LonWebView) webView;
                mClientEvent.onPageFinished(wv, url);
            }
        });

        setWebChromeClient(new WebChromeClient() {
            @Override
            public boolean onShowFileChooser(android.webkit.WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
                return super.onShowFileChooser(webView, filePathCallback, fileChooserParams);
            }

            @Override
            public void onShowCustomView(android.view.View view, CustomViewCallback callback) {
                super.onShowCustomView(view, callback);
            }

            @Override
            public void onShowCustomView(android.view.View view, int requestedOrientation, CustomViewCallback callback) {
                super.onShowCustomView(view, requestedOrientation, callback);
            }

            @Override
            public void onHideCustomView() {
                super.onHideCustomView();
            }

            @Override
            public void onGeolocationPermissionsHidePrompt() {
                super.onGeolocationPermissionsHidePrompt();
            }

            @Override
            public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
                super.onGeolocationPermissionsShowPrompt(origin, callback);
            }

            @Override
            public void onPermissionRequest(PermissionRequest request) {
                super.onPermissionRequest(request);
            }

            @Override
            public void onPermissionRequestCanceled(PermissionRequest request) {
                super.onPermissionRequestCanceled(request);
            }

            @Override
            public boolean onJsTimeout() {
                return super.onJsTimeout();
            }

            @Override
            public void onProgressChanged(android.webkit.WebView view, int newProgress) {
                super.onProgressChanged(view, newProgress);
                if(mChromeClientEvent == null) return;
                LonWebView wv = null;
                if(view instanceof LonWebView) wv = (LonWebView) view;
                mChromeClientEvent.onProgressChanged(wv, newProgress);
            }

            @Override
            public void onReceivedTitle(android.webkit.WebView view, String title) {
                super.onReceivedTitle(view, title);
                if(mChromeClientEvent == null) return;
                LonWebView wv = null;
                if(view instanceof LonWebView) wv = (LonWebView) view;
                mChromeClientEvent.onReceivedTitle(wv, title);
            }

            @Override
            public void onReceivedIcon(android.webkit.WebView view, Bitmap icon) {
                super.onReceivedIcon(view, icon);
                if(mChromeClientEvent == null) return;
                LonWebView wv = null;
                if(view instanceof LonWebView) wv = (LonWebView) view;
                mChromeClientEvent.onReceivedIcon(wv, icon);
            }

            @Override
            public void onReceivedTouchIconUrl(android.webkit.WebView view, String url, boolean precomposed) {
                super.onReceivedTouchIconUrl(view, url, precomposed);
                if(mChromeClientEvent == null) return;
                LonWebView wv = null;
                if(view instanceof LonWebView) wv = (LonWebView) view;
                mChromeClientEvent.onReceivedTouchIconUrl(wv, url, precomposed);
            }

            @Override
            public boolean onCreateWindow(android.webkit.WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
                boolean res = super.onCreateWindow(view, isDialog, isUserGesture, resultMsg);
                if(mChromeClientEvent == null) return res;
                LonWebView wv = null;
                if(view instanceof LonWebView) wv = (LonWebView) view;
                return mChromeClientEvent.onCreateWindow(wv, isDialog, isUserGesture);
            }

            @Override
            public void onCloseWindow(android.webkit.WebView view) {
                super.onCloseWindow(view);
                if(mChromeClientEvent == null) return;
                LonWebView wv = null;
                if(view instanceof LonWebView) wv = (LonWebView) view;
                mChromeClientEvent.onCloseWindow(wv);
            }

            @Override
            public boolean onJsAlert(android.webkit.WebView view, String url, String message, JsResult result) {
                boolean res = super.onJsAlert(view, url, message, result);
                if(mChromeClientEvent == null) return res;
                LonWebView wv = null;
                if(view instanceof LonWebView) wv = (LonWebView) view;
                return mChromeClientEvent.onJsAlert(wv, url, message);
            }

            @Override
            public boolean onJsConfirm(android.webkit.WebView view, String url, String message, JsResult result) {
                boolean res = super.onJsConfirm(view, url, message, result);
                if(mChromeClientEvent == null) return res;
                LonWebView wv = null;
                if(view instanceof LonWebView) wv = (LonWebView) view;
                return mChromeClientEvent.onJsConfirm(wv, url, message);
            }

            @Override
            public boolean onJsPrompt(android.webkit.WebView view, String url, String message, String defaultValue, JsPromptResult result) {
                boolean res = super.onJsPrompt(view, url, message, defaultValue, result);
                if (mChromeClientEvent == null) return res;
                LonWebView wv = null;
                if (view instanceof LonWebView) wv = (LonWebView) view;
                return mChromeClientEvent.onJsPrompt(wv, url, message, defaultValue);
            }

            @Override
            public boolean onJsBeforeUnload(android.webkit.WebView view, String url, String message, JsResult result) {
                boolean res = super.onJsBeforeUnload(view, url, message, result);
                if(mChromeClientEvent == null) return res;
                LonWebView wv = null;
                if(view instanceof LonWebView) wv = (LonWebView) view;
                return mChromeClientEvent.onJsBeforeUnload(wv, url, message);
            }

            @Override
            public boolean onConsoleMessage(ConsoleMessage message) {
                boolean res = super.onConsoleMessage(message);
                if(mChromeClientEvent == null) return res;
                return mChromeClientEvent.onConsoleMessage(message == null ? null : message.message());
            }

            @Override
            public void onConsoleMessage(String message, int lineNumber, String sourceID) {
                super.onConsoleMessage(message, lineNumber, sourceID);
            }
        });
    }

    private void openFileChooserImpl(Activity activity,
                                     ValueCallback<Uri> valueCallback, ValueCallback<Uri[]> valueCallbacks,
                                     WebChromeClient.FileChooserParams fileChooserParams) {
        Intent i = new Intent(Intent.ACTION_GET_CONTENT);
        i.addCategory(Intent.CATEGORY_OPENABLE);
        String[] fileTypes = null;
        String chooserTitle = null;
        if (fileChooserParams != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            fileTypes = fileChooserParams.getAcceptTypes();
            chooserTitle = (String) fileChooserParams.getTitle();
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && fileTypes != null && fileTypes.length > 0) {
            i.putExtra(Intent.EXTRA_MIME_TYPES, fileTypes);
        }
        i.setType("*/*");
        setActivityCallBack(activity, valueCallback, valueCallbacks);
        activity.startActivityForResult(Intent.createChooser(i, TextUtils.isEmpty(chooserTitle) ? "选择文件" : chooserTitle), 6700);
    }

    private void setActivityCallBack(Activity activity,
                                     ValueCallback<Uri> valueCallback, ValueCallback<Uri[]> valueCallbacks) {
        if (!(activity instanceof LonWin)) return;
        final LonWin lonWin = (LonWin) activity;
        final String tagName = this.getClass().getCanonicalName();
        lonWin.addWinLifeListener(tagName, new WinLife() {
            @Override
            public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
                super.onActivityResult(requestCode, resultCode, data);
                lonWin.removeWinLifeListener(tagName);
                if (requestCode == 6700) {
                    if (resultCode == RESULT_OK) {
                        if (null != valueCallback) {
                            Uri result = data == null ? null : data.getData();
                            valueCallback.onReceiveValue(result);
                        }
                        if (null != valueCallbacks) {
                            Uri result = data == null ? null : data.getData();
                            valueCallbacks.onReceiveValue(new Uri[]{result});
                        }
                    } else if (resultCode == RESULT_CANCELED) {
                        if (null != valueCallback) {
                            valueCallback.onReceiveValue(null);
                        }
                        if (null != valueCallbacks) {
                            valueCallbacks.onReceiveValue(null);
                        }
                    }
                }
            }
        });
    }

    /*********************接口事件**************************/

    private ClientEvent mClientEvent;
    private ChromeClientEvent mChromeClientEvent;

    /**
     * 客户端事件
     */
    public abstract static class ClientEvent {
        /**
         * 载入url前，做想做的事情。默认操作是当地址以http开头时，使用该浏览器控件加载它。
         * @param lonWebView 浏览器对象
         * @param url url地址
         * @return 返回true表示url被处理了，false表示未处理，系统可能通过自带的浏览器打开该url
         */
        public Object shouldOverrideUrlLoading(LonWebView lonWebView, String url) {
            return null;
        }

        /**
         * 页面开始加载
         * @param lonWebView 浏览器对象
         * @param url 网址
         * @param favicon 网站图标的位图数据
         */
        public void onPageStarted(LonWebView lonWebView, String url, Bitmap favicon) { }

        /**
         * 当加载一个资源
         * @param lonWebView 浏览器对象
         * @param url 网址
         */
        public void onLoadResource(LonWebView lonWebView, String url) { }

        /**
         * 页面加载结束
         * @param lonWebView 浏览器对象
         * @param url 网址
         */
        public void onPageFinished(LonWebView lonWebView, String url) { }

    }

    /**
     * 浏览器客户端
     */
    public abstract static class ChromeClientEvent {

        /**
         * 页面进度改变
         * @param lonWebView 浏览器对象
         * @param newProgress 进度，0-100
         */
        public void onProgressChanged(LonWebView lonWebView, int newProgress) { }

        /**
         * 收到标题
         * @param lonWebView 浏览器对象
         * @param title 标题内容
         */
        public void onReceivedTitle(LonWebView lonWebView, String title) { }

        public void onReceivedTouchIconUrl(LonWebView view, String url, boolean precomposed) { }

        /**
         * 收到图标
         * @param lonWebView 浏览器对象
         * @param icon 图标位图数据
         */
        public void onReceivedIcon(LonWebView lonWebView, Bitmap icon) { }

        /**
         * 新的浏览器窗口被创建
         * @param lonWebView 浏览器对象
         * @param isDialog 是否为对话框
         * @param isUserGesture 是否为用户手势
         */
        public boolean onCreateWindow(LonWebView lonWebView, boolean isDialog, boolean isUserGesture) {
            return false;
        }

        /**
         * 浏览器某个窗口被关闭
         * @param lonWebView 浏览器对象
         */
        public void onCloseWindow(LonWebView lonWebView) { }

        /**
         * 当JS警示框被弹出前，做想做的事情。返回true和false控制是否弹出浏览器默认的警示框.
         * @param lonWebView 浏览器对象
         * @param url 网址
         * @param message 信息
         */
        public boolean onJsAlert(LonWebView lonWebView, String url, String message) {
            return false;
        }

        /**
         * 当JS信息框被弹出前，做想做的事情。返回true和false控制是否弹出浏览器默认的信息框.
         * @param lonWebView 浏览器对象
         * @param url 网址
         * @param message 信息
         * @param defaultValue 默认内容
         */
        public boolean onJsPrompt(LonWebView lonWebView, String url, String message, String defaultValue) {
            return false;
        }

        /**
         * 当JS被执行前，做想做的事情。
         * @param lonWebView 浏览器对象
         * @param url 网址
         * @param message 信息
         */
        public boolean onJsBeforeUnload(LonWebView lonWebView, String url, String message) {
            return false;
        }

        /**
         * 当JS确认框被弹出前，做想做的事情。返回true和false控制是否弹出浏览器默认的确认框.
         * @param lonWebView 浏览器对象
         * @param url 网址
         * @param message 信息
         */
        public boolean onJsConfirm(LonWebView lonWebView, String url, String message) {
            return false;
        }

        /**
         * 控制台信息输出
         * @param consoleMessage 控制台信息
         */
        public boolean onConsoleMessage(String consoleMessage) {
            return false;
        }

    }

    /**
     * JavaScript的接口事件
     */
    public abstract static class JavascriptInterface {
        /**
         * 在js代码中调用，触发java中对应的接口函数
         *
         * @param str 内容
         */
        public void send(String str) {
        }

        /**
         * 在js代码中调用，触发java中对应的接口函数
         *
         * @param tag 标签
         * @param str 内容
         */
        public void sendWithTag(String tag, String str) {
        }

        /**
         * 在js代码中调用，触发java中对应的接口函数
         *
         * @param arr 内容数组
         */
        public void sendArray(String[] arr) {

        }

        /**
         * 在js代码中调用，触发java中对应的接口函数
         *
         * @param tag 标签
         * @param arr 内容数组
         */
        public void sendArrayWithTag(String tag, String[] arr) {

        }
    }

    @Override
    protected void onVisibilityChanged(@NonNull android.view.View v, int visibility) {
        super.onVisibilityChanged(v, visibility);
        viewImpl.callVisibilityChangeCallback(v, visibility);
        onViewVisibilityChanged(v, visibility);
    }

    @Override
    protected void onFocusChanged(boolean gainFocus, int direction, @Nullable Rect previouslyFocusedRect) {
        super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
        viewImpl.callFocusChangeCallback(gainFocus, direction, previouslyFocusedRect);
        onViewFocusChanged(gainFocus, direction, previouslyFocusedRect);
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        viewImpl.callViewDestroy();
        onViewDestroy();
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        viewImpl.callViewDestroy();
        onViewCreate();
    }

    @Override
    protected void onSizeChanged(int newWidth, int newHeight, int oldWidth, int oldHeight) {
        super.onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
        viewImpl.callSizeChangeCallback(newWidth, newHeight, oldWidth, oldHeight);
        onViewSizeChange(newWidth, newHeight, oldWidth, oldHeight);
    }

}
